//
//  BluetoothDataCache.swift
//  DaRings
//
//  Created by 尹琼 on 2022/11/9.
//

import UIKit
import CRPSmartRing
import MYModule
import SQLite
import SwiftDate
import CoreBluetooth

public protocol BluetoothResponderDelegate {
    
    
    /// 是否在当前控制器弹窗强制升级弹窗
    /// - Parameters:
    ///   - responder: responder
    ///   - atCurrentViewController: 当前控制器
    func shoudShowUpgradeAlert(responder: BluetoothResponder, atCurrentViewController: UIViewController) ->Bool
    
    /// 去固件升级页面
    /// - Parameters:
    ///   - responder: responder
    ///   - provider: ota info
    ///   - fileInfo: file info
    /// - Returns: 控制器
    func willPushToUpgradeController(responder: BluetoothResponder, provider: OTAProvider, fileInfo: OTAProvider.FileInfo) ->UIViewController
    
    
    /// 即将去正在锻炼中的锻炼页面
    /// - Parameters:
    ///   - responder: responder
    ///   - trainModel: model
    func willPushToTrainingController(responder: BluetoothResponder, trainModel: TrainingModel)
    
    
    /// 锻炼已经结束
    /// - Parameters:
    ///   - responder: responder
    ///   - trainModel: model
    func trainingIsEnd(responder: BluetoothResponder, trainModel: TrainingModel?)
    
}


public final class BluetoothResponder: NSObject {
    
    
    /// 是否可以弹出心率预警
    private var showHeartRateAlert: Bool = false
    
    /// 记录的目标设置
    private var goalModel: ExerciseGoalsModel?
    
    private var bettyAlertController: BluetoothAlertController?
    
    /// 低电量无法点击弹窗
    private var deMeasureBettyAlertConller: UIAlertController?
    
    private var heartRateAlertController: BluetoothAlertController?
    
    /// 日常目标达成弹窗
    private var dailyExerciseAlertController: BluetoothAlertController?
    
    /// 日常锻炼目标达成数据元组
    private var recursiveAlertTuples: [(type: BluetoothAlertType, value: String)] = []
    
    private var trainingAlertController: BluetoothAlertController?
    
    private var minderController: BluetoothAlertController?
    
    private var updateTimer: Timer?
    
    
    public var currentTraining: CurrentTraining?
    

    public static var shared = BluetoothResponder()
    
    
    public var delegate: BluetoothResponderDelegate?
    
    
    
    public func addNotifacations() {
        
        let selectors: [(selector: Selector, type: NotifactionType)] = [
            (#selector(deviceState(noti:)), .deviceState),
            (#selector(bluetoothState(noti:)), .bluetoothState),
            (#selector(steps(noti:)), .activity),
            (#selector(heartRate(noti:)), .singleHeartRate),
            (#selector(realTimeHeartRate(noti:)), .realTimeHeartRate),
            (#selector(HRV(noti:)), .singleHRV),
            (#selector(stress(noti:)), .singleStress),
            (#selector(spO2(noti:)), .singleBloodOxygen),
            (#selector(sportList(noti:)), .sportList),
            (#selector(sportState(noti:)), .sportState),
            (#selector(bettry(noti:)), .battery),
            (#selector(activityReminderInfo(noti:)), .reminder),
            
            
        ]
        
        selectors.forEach {
            
            NotificationCenter.default.addObserver(self, selector: $0.selector, name: $0.type.name, object: nil)
            
        }
        

    }
    
    /// 设备连接通知
    /// - Parameter noti:
    @objc public func deviceState(noti: NSNotification) {
        
//        firstUserAlert()
        
        guard let dict = noti.userInfo as? [String: Any], let state = dict["result"] as? CRPSmartRing.CRPState else { return }
        
        saveLocaDeviceInfo {deviceInfo in
            self.OTACheck(deviceInfo: deviceInfo)
        }
        
        BluetoothManager.shared.isConnectedForConnectState {
            
            self.setUserInfo()
            
            self.setGoalsInfo()
            
            /// 是否在锻炼中
            self.trainingType()
            
            // 开启定时测量心率 （正数 * 5分钟）以设备默认设置为准
            BluetoothManager.shared.setTimingHeartRate(6)
            
            // 开启定时测量HRV （正数 * 5分钟）以设备默认设置为准
            BluetoothManager.shared.setTimingHRV(6)
            
            // 开启定时测量血氧 （正数 * 5分钟）以设备默认设置为准
            BluetoothManager.shared.setTimingO2(6)
            
            // 开启体温测量
            BluetoothManager.shared.setSleepTemperatureState(open: true)
            
            // 开启步数同步
            BluetoothManager.shared.getSteps()
            
            // 同步点测数据
            self.measuredData()
            
            // 同步今日数据
            self.updateTodayDatas()
            
        }
        
        self.postUpdateUINotifaction(type: .deviceState, result: state)
        
    }
    
    
    /// 设置用户信息
    public func setUserInfo() {
        
        /// 设置用户信息
        let userInfo = UserCacheManagement.userInfo()
        let genderOption: CRPGenderOption = userInfo.sex == .female ? .female : .male
        let crpUserInfo = CRPUserInfoModel(height: userInfo.height, weight: userInfo.weight, age: userInfo.age, gender: genderOption, stepLength: userInfo.steplength)
        BluetoothManager.shared.setUserinfo(crpUserInfo)
        
    }
    
    
    /// 设置目标设置信息
    public func setGoalsInfo() {
        /// 判断是否需要设置目标
        let goalModel = ExerciseGoalsModel.currentGoal(weekDay: Date().weekday)
        if goalModel.syncRecord == 0 {
            
            let model = CRPTrainingGoalsModel(step: goalModel.step, kcal: goalModel.kcal, distance: goalModel.distance, exerciseTime: goalModel.exerciseTime)
            BluetoothManager.shared.setNormalTrainingGoal(model)
            goalModel.syncRecord = 1
            goalModel.updateData()
            
        }
        
    }
    
    
    /// 单独更新一天睡眠
    /// - Parameter date: 日期
    public func updateSleepData(of date: Date) {
        
        // 1天睡眠
        BluetoothManager.shared.getSleepDatas(of: date, backward: 1) {
            
            BluetoothResponder.shared.postUpdateUINotifaction(type: NotifactionType.sleep)
            
        }
    }
    
    /// 今日全天类数据同步
    public func updateTodayDatas() {
        
      

        // 获取今日数据
        let date = Date()
        DispatchQueue.main.async {
            
            /// 更新今天睡眠
            self.updateSleepData(of: date)
            
            // 1天活动
            BluetoothManager.shared.getTrainingDatas(of: date, backward: 1) {

                BluetoothResponder.shared.postUpdateUINotifaction(type: NotifactionType.activity)
            }
            
            // 定时更新的数据同步
            self.addUpdateTimer()
            
            // 运动列表
            BluetoothManager.shared.getTrainingtRecordList()
            
            
            // 15天血氧同步
            BluetoothManager.shared.getTimingO2s(of: date, backward: 15)
            
        }
        
    }
    
    public func addUpdateTimer() {
        
        if self.updateTimer != nil {
            self.updateTimer?.invalidate()
            self.updateTimer = nil
        }
        
        let date = Date()
        self.timingData(date: date)
        let updateTimer = Timer.scheduledTimer(withTimeInterval: 60, repeats: true, block: {[weak self] _ in
            
            let date = Date()
            self?.timingData(date: date)
        
        })
        
        RunLoop.current.add(updateTimer, forMode: .common)
        self.updateTimer = updateTimer
        
    }
    
    /// 定时获取数据同步
    public func timingData(date: Date) {
        
        // 一天心率更新
        BluetoothManager.shared.getTimingHeartRates(of: date, backward: 1) {
            
            BluetoothResponder.shared.postUpdateUINotifaction(type: NotifactionType.heartRate)
        }
        
        // 获取1天步数归档
        BluetoothManager.shared.getStepArchiveDatas(of: date, backward: 1) {
            
            BluetoothResponder.shared.postUpdateUINotifaction(type: NotifactionType.activity)
        }
        
        // 1天HRV 及压力
        BluetoothManager.shared.getTimingHRVs(of: date, backward: 1) {
            
            BluetoothResponder.shared.postUpdateUINotifaction(type: NotifactionType.HRV)
        }
        
        // 1天血氧同步
        BluetoothManager.shared.getTimingO2s(of: date, backward: 1) {
            
            BluetoothResponder.shared.postUpdateUINotifaction(type: NotifactionType.bloodOxygen)
        }
        
        
    }
    
    
    /// 点测数据同步
    public func measuredData() {
        
        BluetoothManager.shared.getHeartRecordDatas {
            BluetoothResponder.shared.postUpdateUINotifaction(type: NotifactionType.singleHeartRate)
        }
        
        BluetoothManager.shared.getO2RecordDatas {
            BluetoothResponder.shared.postUpdateUINotifaction(type: NotifactionType.singleBloodOxygen)
        }
        
        BluetoothManager.shared.getHRVRecordDatas {
            BluetoothResponder.shared.postUpdateUINotifaction(type: NotifactionType.singleHRV)
        }
        
        BluetoothManager.shared.getStressRecordDatas {
            
            BluetoothResponder.shared.postUpdateUINotifaction(type: NotifactionType.singleStress)
        }
        
    }
    
    /// 蓝牙连接成功
    /// - Parameter noti:
    @objc public func bluetoothState(noti: NSNotification) {
        
        guard let dict = noti.userInfo as? [String: Any], let state = dict["result"] as? CRPSmartRing.CRPBluetoothState else { return }
        
        postUpdateUINotifaction(type: NotifactionType.type(of: noti.name), result: state)
    }
    
    
    @objc public func steps(noti: NSNotification) {
        
        guard let dict = noti.userInfo as? [String: Any], let result = dict["result"] as? CRPSmartRing.CRPStepModel else {
            return
        }
        
        let time = Int(Double(result.steps) * 0.008 * 60.0)
        
        // TODO: time 指令返回来的是锻炼的时长
//        if time < 0 {
//            time = Int(Double(result.steps) * 0.008 * 60.0)
//        }
//
        let date = Date()
        
        var stepModel: ActivityModel
        if let model = ActivityModel.day(date: date) {
            stepModel = model
            
        } else {
            
            stepModel = ActivityModel()
           
        }
        
        let appleStep = result.steps - stepModel.step
        let appleKcal = result.calory - stepModel.calorie
        let appleDistance = result.distance - stepModel.distance
        
        stepModel.adress = DeviceInfo.current().adress ?? ""
        stepModel.date = date.sqlDate()
        stepModel.step = result.steps
        stepModel.distance = result.distance
        stepModel.time = time
        stepModel.calorie = result.calory
        
        // 查询 目标设置
        let goalModel = ExerciseGoalsModel.currentGoal(weekDay: date.weekday)
        if goalModel.isEmpty {
            
            let userInfoModel = UserCacheManagement.userInfo()
            let bmi = userInfoModel.BMI(height: Float(userInfoModel.weight)/100, weight: Float(userInfoModel.height))
            goalModel.step = userInfoModel.getGoalSteps(bmi: bmi)
            goalModel.kcal = userInfoModel.getGoalCalories(bmi: bmi)
            goalModel.exerciseTime = userInfoModel.getGoalExerciseTime(bmi: bmi)
            goalModel.updateData()
            
        }
        
        let step_target = goalModel.step
        let calories_target = goalModel.kcal
        let duration_target = goalModel.exerciseTime
        
    

        stepModel.goalStep = step_target
        stepModel.goalCalorie = calories_target
        stepModel.goalTime = duration_target
        
        let save = stepModel.updateData()
        if save == false {
            return
        }
        
        var alertTuples = [(type: BluetoothAlertType, value: String)]()
        if stepModel.step >= stepModel.goalStep {
            
            let tuple: (type: BluetoothAlertType, value: String) = (BluetoothAlertType.activityStepGoal, "\(stepModel.goalStep)")
            alertTuples.append(tuple)
        }
        if stepModel.calorie >= stepModel.goalCalorie {
            let tuple: (type: BluetoothAlertType, value: String) = (BluetoothAlertType.activityCaloriesGoal, "\(stepModel.goalCalorie)")
            alertTuples.append(tuple)
        }
        
        let minute = stepModel.time/60
        if minute > 1 && minute >= stepModel.goalTime {
            
            let tuple: (type: BluetoothAlertType, value: String) = (BluetoothAlertType.activityTimeGoal, "\(stepModel.goalTime)")
            alertTuples.append(tuple)
            
        }
        
        dailyExerciseAlerts(alertTuples: alertTuples)
        
        postUpdateUINotifaction(type: NotifactionType.type(of: noti.name), result: result)
        
        if appleStep > 0 {
            // 更新苹果健康
            HealthKitManager.sharedInstance.update(step: appleStep, kcal: appleKcal, distance: appleDistance)
            
        }
        
        
    }
    
    /// 单次心率测量
    /// - Parameter noti: noti
    @objc public func heartRate(noti: NSNotification) {
        guard let dict = noti.userInfo as? [String: Any], let heartRate = dict["result"] as? Int else {
            return
        }
        let date = Date()
        let singleHeartRateModel = SingleHeartRateModel.aModel(from: date.timeIntervalSince1970) ?? SingleHeartRateModel()
        singleHeartRateModel.adress = DeviceInfo.current().adress ?? ""
        singleHeartRateModel.heartRate = heartRate
        singleHeartRateModel.end = date.timeIntervalSince1970
        let save = singleHeartRateModel.updateData()
        
        postUpdateUINotifaction(type: NotifactionType.type(of: noti.name))
        
        if save == false {
            return
        }
        
        // 更新苹果健康
        HealthKitManager.sharedInstance.uploadHR(heartRate: heartRate)
        
    }
    
    // 持续心率（一般只用于显示，不用存储）
    @objc public func realTimeHeartRate(noti: NSNotification) {
        guard let dict = noti.userInfo as? [String: Any], let model = dict["result"] as? ReceiveRealTimeHeartRateModel else {
            return
        }
        
        print("锻炼心率: \(model.heartRate)")
        
        postUpdateUINotifaction(type: NotifactionType.type(of: noti.name), result: model)
        
        
    }
    
    @objc public func HRV(noti: NSNotification) {
        guard let dict = noti.userInfo as? [String: Any], let hrv = dict["result"] as? Int else {
            return
        }
        let date = Date()
        let hrvModel = SingleHRVModel.aModel(from: date.timeIntervalSince1970) ?? SingleHRVModel()
        hrvModel.adress = DeviceInfo.current().adress ?? ""
        hrvModel.hrv = hrv
        hrvModel.end = date.timeIntervalSince1970
        hrvModel.updateData()
        
        postUpdateUINotifaction(type: NotifactionType.type(of: noti.name), result: hrv)
        
    }
    
    @objc public func stress(noti: NSNotification) {
        
        guard let dict = noti.userInfo as? [String: Any], let stress = dict["result"] as? Int else {
            return
        }
        
        let date = Date()
        let stressModel = SingleStressModel.aModel(from: date.timeIntervalSince1970) ?? SingleStressModel()
        stressModel.adress = DeviceInfo.current().adress ?? ""
        stressModel.stress = stress
        stressModel.end = date.timeIntervalSince1970
        stressModel.updateData()
        
        postUpdateUINotifaction(type: NotifactionType.type(of: noti.name), result: stress)
    }
    
    @objc public func spO2(noti: NSNotification) {
        guard let dict = noti.userInfo as? [String: Any], let result = dict["result"] as? Int else {
            return
        }
        let date = Date()
        let bloodOxygenModel = SingleBloodOxygenModel.aModel(from: date.timeIntervalSince1970) ?? SingleBloodOxygenModel()
        bloodOxygenModel.adress = DeviceInfo.current().adress ?? ""
        bloodOxygenModel.o2 = result
        bloodOxygenModel.end = date.timeIntervalSince1970
        bloodOxygenModel.updateData()
        
        postUpdateUINotifaction(type: NotifactionType.type(of: noti.name), result: result)
       
    }
    
    
    @objc public func sportList(noti: NSNotification) {
        
        guard let dict = noti.userInfo as? [String: Any], let result = dict["result"] as? [CRPTrainingRecord] else {
            return
        }
        
        let records = result.filter({ $0.startTime > 0 }).reversed()
        let ids = records.map { $0.id }
        
        if ids.isEmpty {
            self.postUpdateUINotifaction(type: NotifactionType.type(of: noti.name))
            return
        }
        
        var recordCount = 0
        BluetoothManager.shared.getTrainingRecordDatas(ids: ids) { model, sportModel in
            
            let id = sportModel.id
            
            recordCount += 1
            if recordCount == ids.count {
                self.postUpdateUINotifaction(type: NotifactionType.type(of: noti.name))
            }
            
            //TODO: - 如果戒指意外结束了，手机还在锻炼中的界面，那么就直接跳转详情页
            if id == result.last?.id, model?.endTime != 0, model?.trainingState == 0 {
                
                self.delegate?.trainingIsEnd(responder: self, trainModel: model)
                return
            }

            if id == result.last?.id, let currentTraining = self.currentTraining, currentTraining.state != .unstarted, let model = model, currentTraining.type.rawValue == model.type, model.endTime == 0 {
                log.debug("type = \(model.type) 锻炼中再次进入")
                self.pushToCurrentTrainingController(trainModel: model)
                if model.trainingState == 0 {
                    model.trainingState = currentTraining.state.rawValue
                    model.updateData()
                }
            }
        }
            
    }
    
    
    @objc public func sportState(noti: NSNotification) {
        guard let dict = noti.userInfo as? [String: Any], let type = dict["result"] as? CRPSmartRing.CRPTrainingType else {
            return
        }
        
        /// 开启心率预警
        if type.rawValue >= 0 && type.rawValue <= 253 {
            showHeartRateAlert = true
        } else {
            showHeartRateAlert = false
        }
        
        postUpdateUINotifaction(type: NotifactionType.type(of: noti.name), result: type)
        
        
        

    }
    
    
    /// 电量变化
    /// - Parameter noti:
    @objc public func bettry(noti: NSNotification) {
        
        guard let dict = noti.userInfo as? [String: Any], let result = dict["result"] as? Int else {
            return
        }
        
        postUpdateUINotifaction(type: NotifactionType.type(of: noti.name), result: result)
        
        guard let currentBattery = BluetoothManager.shared.currentBattery else { return }
        
        if currentBattery < 10 && currentBattery > 0 {
            
            /// 低电量提醒
            showLowpowerBetty(value: currentBattery)
            
        }
        
        if  currentBattery > 30 {
            bettyAlertController = nil
        }
    }
    
    @objc public func activityReminderInfo(noti: NSNotification) {
        
        guard let dict = noti.userInfo as? [String: Any], let model = dict["result"] as? ReminderModel else {
            return
        }
        
        minderAlert(model: model)
        
    }
    
}


public extension BluetoothResponder {
    
    func postUpdateUINotifaction(type: NotifactionType?, result: Any? = nil) {
        
        guard let type = type else {
            return
        }
        
        var userInfos: [String: Any] = ["type": type]
        if result != nil {
            userInfos["result"] = result
        }
        NotificationCenter.default.post(name: .kUpdateUINotification, object: nil, userInfo: userInfos)
        
    }
    
    func addUpdateUINotifaction(observer: Any, selector: Selector) {
        
        NotificationCenter.default.addObserver(observer, selector: selector, name: .kUpdateUINotification, object: nil)
        
        
    }
    
}


// MARK: - 强制升级
extension BluetoothResponder {
    
    /// 设备信息保存本地
    /// - Parameter handle: 设备信息
    public func saveLocaDeviceInfo(handle: ((_ deviceInfo: DeviceInfo) ->Void)?) {
        
        let deviceInfo = DeviceInfo.current()
        if BluetoothManager.shared.deviceState == .connected {
            // 保存设备信息
            if let connectDiscovery = BluetoothManager.shared.connectDiscovery {
                deviceInfo.save(of: connectDiscovery)
            }
            
            var save = 0
            // mac 地址 和 ver 额外接口获取
            var saveAll = 3
            if let _ = deviceInfo.adress {
                saveAll = 2
            } else {
                BluetoothManager.shared.getMac { value, error in
                    deviceInfo.adress = value
                    save += 1
                    if save == saveAll {
                        deviceInfo.save()
                        handle?(deviceInfo)
                    }
                }
            }
            
            BluetoothManager.shared.getSoftver { value, error in
                deviceInfo.versoin = value
                save += 1
                if save == saveAll {
                    deviceInfo.save()
                    handle?(deviceInfo)
                }
            }
            
            BluetoothManager.shared.githash { value, error in
                deviceInfo.gitHash = value
                save += 1
                if save == saveAll {
                    deviceInfo.save()
                    handle?(deviceInfo)
                }
            }
            
            BluetoothManager.shared.getRingInfo { model, error in
                
                if let adress = deviceInfo.adress {
                    let color = DeviceInfo.RingColorType(rawValue: model.color) ?? .unkown
                    let info = DeviceInfo.RingInfo(adress: adress, color: color, size: model.size, type: model.type)
                    info.save()
                }
                
            }
        
        }
        
    }
    
    public func OTACheck(deviceInfo: DeviceInfo, sucess: ((_ fileINfo: OTAProvider.FileInfo?) ->Void)? = nil, failure: API.failureHandle? = nil) {
        
        guard let mac = deviceInfo.adress, let version = deviceInfo.versoin else { return }
        
        let provider = OTAProvider()
        provider.upgrade(target: .production(mac: mac, version: version)) { fileINfo in
            
            sucess?(fileINfo)
            
            // 判断是否需要强制升级
            guard let fileInfo = fileINfo else {
                return
            }
            
            /// 空的不需要升级
            if fileInfo.isEmpty {
                return
            }
            
            /// 强制升级
            if fileInfo.type == .forced {
                
                self.upgradeAlert(provider: provider, fileInfo: fileInfo)
            }
            
            
        } failure: {
            
            failure?($0)
        }
        
    }
    
    /// 强制升级弹窗
    /// - Parameter provider:
    public func upgradeAlert(provider: OTAProvider, fileInfo: OTAProvider.FileInfo) {
        
        guard let currentVC = UIViewController.currentViewController() else {
            return
        }
        
        showDelegateError()
        
        let show: Bool = delegate!.shoudShowUpgradeAlert(responder: self, atCurrentViewController: currentVC)
        
        // 在升级页面就不需要
        if !show {
            return
        }
        
        let message = getCurrentLanguage() == .chinese ? fileInfo.log : fileInfo.log_en
        let title = fileInfo.version
       
        UIAlertController.showConfirm(title: title, message: message) { _ in
            
            self.willUpgrade(provider: provider, fileInfo: fileInfo)
        }
    }
    
    /// 即将强制升级
    /// - Parameter provider:
    public func willUpgrade(provider: OTAProvider, fileInfo: OTAProvider.FileInfo) {
        
        let currentVC = UIViewController.currentViewController()
        
        guard let currentVC = currentVC else {
            return
        }

        showDelegateError()
        let vc = delegate!.willPushToUpgradeController(responder: self, provider: provider, fileInfo: fileInfo)
            
        // 在升级页面就不需要
        if currentVC.classForCoder == vc.classForCoder {
            return
        }
        
        currentVC.navigationController?.pushViewController(vc, animated: true)
    }
    
}

// MARK: - 前台弹窗 / 后台 通知
extension BluetoothResponder {
    
    @discardableResult
    public func alert(of type: BluetoothAlertType, valueStr: String, handler: (() -> Void)? = nil) ->BluetoothAlertController? {
        
        if UIApplication.shared.applicationState == .background {
            
            UNNotificationRequest.warning(identifier: type.rawValue, content: type.notifactionContent(value: valueStr))
            
        } else {
            
            if let vc = UIViewController.rootViewController() {
                
                let alert = BluetoothAlertController(type: type, dataString: valueStr, handler: handler)
                vc.present(alert, animated: true)
               return alert
 
            }
        }
        
        return nil
        
    }
    
}


// MARK: - 久坐提醒
extension BluetoothResponder {
    
    public func minderAlert(model: ReminderModel) {
        
        if model.isReminder == 0 {
            return
        }
        
        if let _ = minderController {
            return
        }
        
        minderController = alert(of: .sedentary, valueStr: "", handler: {[weak self] in
            self?.minderController = nil
        })
        
    }
    
}
// MARK: - 目标达成
extension BluetoothResponder {
    
    /// 锻炼目标达成提醒
    /// - Parameter type:
   public func trainingGoalAlert(type: BluetoothAlertType) {
        
        if let _ = trainingAlertController {
            return
        }
        
        
        trainingAlertController = alert(of: type, valueStr: "", handler: {
            self.trainingAlertController = nil
        })
        
    }
    
    
    /// 日常锻炼目标
    public func dailyExerciseAlerts(alertTuples: [(type: BluetoothAlertType, value: String)], handler: (() ->Void)? = nil) {
        
        self.recursiveAlertTuples.append(contentsOf: alertTuples)
        
        // 弹出
        recursiveDailyExerciseAlert(alertTuples: alertTuples, index: 0)
        
    }
    
    fileprivate func recursiveDailyExerciseAlert(alertTuples: [(type: BluetoothAlertType, value: String)], index: Int) {
        
        if let _ = dailyExerciseAlertController {
            return
        }
        if index >= alertTuples.count {
            // 全部弹出，删除数据
            self.recursiveAlertTuples.removeAll()
            self.dailyExerciseAlertController = nil
            return
        }
        
        let alertTuple = alertTuples[index]
        let achievementModel = DailyExerciseAchievement.current()
        let activityModel = ActivityModel.day(date: Date())
        
        var alertAble: Bool = true
        
        switch alertTuple.type {
            
        
        case .activityStepGoal:
            
            if achievementModel.stepAlertAble {
                
                achievementModel.step += 1
                achievementModel.stepAlertAble = false
                achievementModel.save()
                
                activityModel?.stepAchievement += 1
                activityModel?.updateData()
                
            } else {
                
                alertAble = false
            }
            
            break
            
        case .activityCaloriesGoal:
            
            if achievementModel.calorieAlertAble {
                
                achievementModel.calorie += 1
                achievementModel.calorieAlertAble = false
                achievementModel.save()
                
                activityModel?.calorieAchievement += 1
                activityModel?.updateData()
                
            } else {
                
                alertAble = false
            }
            
            break
            
        case .activityTimeGoal:
            
            if achievementModel.timeAlertAble {
                achievementModel.time += 1
                achievementModel.timeAlertAble = false
                achievementModel.save()
                
                activityModel?.timeAchievement += 1
                activityModel?.updateData()
                
            } else {
                
                alertAble = false
            }
            break
            
        default:
            alertAble = false
            break
        }
        
        if !alertAble {
            self.recursiveDailyExerciseAlert(alertTuples: alertTuples, index: index + 1)
            return
        }
        
        dailyExerciseAlertController = alert(of: alertTuple.type, valueStr: alertTuple.value, handler: {[weak self] in
            self?.dailyExerciseAlertController = nil
            self?.recursiveDailyExerciseAlert(alertTuples: alertTuples, index: index + 1)
            
        })
        
    }
    
}

// MARK: - 心率预警
extension BluetoothResponder {
    
    
    /// 心率预警
    /// - Parameter value: 心率值
    public func heartRateMaxAlert(_ heartRate: Int) {
        
        if let _ = self.heartRateAlertController {
            return
        }

        let userInfo = UserCacheManagement.userInfo()
        // 未开启心率提醒
        if userInfo.heartRemind == false {
            return
        }

        if let _ = heartRateAlertController {
            return
        }

        let heartRateMax = UserCacheManagement.userInfo().warningMxHR
        
        // 当心率小于最大心率时，下一次 心率大于最大心率 又可以弹窗
        if heartRate <= heartRateMax {
            showHeartRateAlert = true
        }

        if heartRate > heartRateMax && showHeartRateAlert == true {

            let type = BluetoothAlertType.heartRate
            let valueStr = "\(heartRateMax)"

            self.heartRateAlertController = alert(of: type, valueStr: valueStr) {

                self.showHeartRateAlert = false
                self.heartRateAlertController = nil

            }

        }


    }
    
    
}

// MARK: - 低电量提醒
extension BluetoothResponder {
    
    /// 低电量提醒
    /// - Parameter value:
    public func lowpowerBettyAlert(value: Int) {
        
        if let _ = bettyAlertController {
            return
        }
        
        let type = BluetoothAlertType.lowPowerBettry
        let valueStr = "10%"
        
        if value < 10 && value > 0 {
            
            self.bettyAlertController = alert(of: type, valueStr: valueStr, handler: {
                self.bettyAlertController = nil
            })
        }
    }
    
    public func showLowpowerBetty(value: Int) {
        let userInfo = UserCacheManagement.userInfo()
        // 未开启低电量提醒
        if userInfo.lowBatteryReminder == false {
            return
        }
        
        lowpowerBettyAlert(value: value)
    }
    
    /// 锻炼前检查
    public func willTrainingment(canTraining: @escaping () ->Void) {
        
        willBeginActionWithBattery(title: "dialog_device_cant_training_battery_low".language, handler: canTraining)
        
    }
    
    /// 单击检测前检查电量
    /// - Parameter canMeasurement: block
    public func willMeasurement(canMeasurement: @escaping () -> Void) {
        // 检查设备电量
        
        willBeginActionWithBattery(title: "dialog_device_battery_low".language, handler: canMeasurement)
        
    }
    
    public func willBeginActionWithBattery(title: String, handler: @escaping () -> Void) {
        
        if BluetoothManager.shared.deviceState != .connected {
            return
        }
        
        guard let currentBattery = BluetoothManager.shared.currentBattery else { return }
        
        if currentBattery < 10 && currentBattery > 0 {
            
            if let currentVC = UIViewController.rootViewController() {
                deMeasureBettyAlertConller = UIAlertController.showAlertOk(title: title, message: "", in: currentVC) {[weak self] _ in
                    
                    self?.deMeasureBettyAlertConller = nil
                }
            }
            
        } else {
            
            handler()

        }
    }
}

// MARK: - 戒指检测状态
extension BluetoothResponder {
    
    /// 锻炼状态检测
    public func trainingType() {
        
        BluetoothManager.shared.getTraingingState { type, state, error in
           
            
            self.currentTraining = CurrentTraining(type: type, state: state)
            
        } 
        
    }
    
    
    /// 继续锻炼
    /// - Parameter trainModel: model
    public func pushToCurrentTrainingController(trainModel: TrainingModel) {
        
        showDelegateError()
        self.showHeartRateAlert = true
        delegate?.willPushToTrainingController(responder: self, trainModel: trainModel)
            
        
    }
      
}


// MARK: - Bluetooth Data other Notification
public extension Notification.Name {
    
    /// 更新UI的通知，传递 NotifactionTye
    static let kUpdateUINotification = Notification.Name.init(rawValue: "updateUserUINotification")
    
    
}

extension BluetoothResponder {
    
   public struct CurrentTraining {
        
       public var type: CRPTrainingType
       public var state: CRPTrainingState
        
    }
    
    public enum BluetoothResponderError: Error {
        
        case delegateError(message: String)
    }
    
    public func showDelegateError() {
        
        if delegate == nil {
          print(BluetoothResponderError.delegateError(
                message: """
                  必须实现代理 BluetoothResponderDelegate 不然固件升级与锻炼中逻辑不完整
                  
                  推荐可以在 TabBar 控制器，或者首页 控制器 实现
                  不推荐 在AppDelegate 中实现

                  """
            ))
        }
        
    }
    
}



